﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows;

using P2PTransmit.Modal;
using P2PTransmit.Modal.Protocol;

namespace P2PTransmit.ViewModal
{
    public class P2PTransmitViewModal : INotifyPropertyChanged
    {

        #region 字段

        private Mutex                                           ApplicationLocker;
        private bool                                            ApplicationLock;

        internal Setting                                        Setting;

        private  Service.ServiceManager                         ServiceManager;
        internal Service.TransmitService                        TransmitService;
        internal Service.MessageService                         MessageService;
        internal Service.ConnectionService                      ConnectionService;
        internal TimePeroidClass                                Timer;

        public Command.FileDrop                                 FileDrop;

        #endregion


        public P2PTransmitViewModal()
        {
            ApplicationLock = false;
            //防止多次运行
            ApplicationLocker = new Mutex( true, "P2pTransmmit", out ApplicationLock );
            if ( !ApplicationLock )
            {
                System.Windows.MessageBox.Show(
                    "程序已经运行，请不要重复启动",
                    "警告",
                    System.Windows.MessageBoxButton.OK,
                    System.Windows.MessageBoxImage.Warning );
                Environment.Exit( 0 );
            }

            //初始化服务
            ServiceManager = new Service.ServiceManager();
            Setting = new Setting();

            if ( !string.IsNullOrEmpty( Setting.MachineName ) )
                Service.ServiceManager.LocalMachineName = Setting.MachineName;

            #region Message

            MessageService = new Service.MessageService( 4121 );
            ServiceManager.AddService<Message>( MessageService, MessagePool );
            MessageService.OnMessageReceive += () =>
            {
                NoticeIcon = "";
                NoticeMessage = "有新的消息";
            };
            #endregion

            #region Connection

            ConnectionService = new Service.ConnectionService( 1933 );
            ServiceManager.AddService<Connection>( ConnectionService, ActiveConnection );
            ConnectionService.OnConnectionNameChanged += (name) =>
            {
                var find = from e in ActiveConnection where e.MachineName == name select e;
                NoticeIcon = "";
                NoticeMessage = $"{find.Single().MachineName}\x20\x20已经改名为:\x20{name}";
            };

            ConnectionService.OnFindConnection += (name) =>
            {
                NoticeIcon = "";
                NoticeMessage = $"找到主机{name}";
            };
            #endregion

            #region Transmit

            Timer = new TimePeroidClass();
            TransmitService = new Service.TransmitService( 9734 );
            ServiceManager.AddService<NetworkTask>( TransmitService, Task );
            TransmitService.OnTransmitReceive += (task) =>
            {
                if ( Setting.AutoReceiveFile ||
                MessageBox.Show( $"是否接受文件", "询问", MessageBoxButton.YesNo, MessageBoxImage.Question ) == MessageBoxResult.Yes )
                {
                    var core = new Service.Core.TransmitCore( Setting.SavePath, Setting.ErrorPath, true );
                    core.OnTaskFinish += (finish) =>
                    {
                        Task.Remove( finish );
                        FinishTask.Add( finish );
                        NoticeIcon = "";
                        var start = new DateTime( finish.StartStamp );
                        var last = DateTime.Now;
                        NoticeMessage = $"文件传输完毕,耗时:{( last - start ).TotalMilliseconds}ms";

                    };
                    core.OnFileError += (msg) =>
                    {
                        NoticeIcon = "";
                        NoticeMessage = $"文件操作出错，{msg}";
                    };
                    core.OnNetworkError += (msg) =>
                    {
                        NoticeIcon = "";
                        NoticeMessage = $"网络连接错误，{msg}";
                    };
                    core.OnTransmitError += (msg) =>
                    {
                        NoticeIcon = "";
                        NoticeMessage = $"传输错误，{msg}";
                    };
                    Timer.TimerPeroid += () =>
                    {
                        task.Speed = task.CurrentPosition - task.SpeedTime;
                        task.SpeedTime = task.CurrentPosition;
                    };
                    core.Accept( ref task );
                    Task.Add( task );
                    NoticeIcon = "";
                    NoticeMessage = "开始接收文件，传输开始";
                    return core.Port;//返回一个传输端口
                }
                else
                {
                    return 0;
                }
            };
            TransmitService.OnUserAccept += (task) =>
            {
                var core = new Service.Core.TransmitCore( Setting.SavePath, Setting.ErrorPath, false );
                core.OnFileError += (msg) =>
                {
                    NoticeIcon = "";
                    NoticeMessage = $"文件操作出错，{msg}";
                };
                core.OnNetworkError += (msg) =>
                {
                    NoticeIcon = "";
                    NoticeMessage = $"网络连接错误，{msg}";
                };
                core.OnTransmitError += (msg) =>
                {                    
                    NoticeIcon = "";
                    NoticeMessage = $"传输错误，{msg}";
                };

                core.OnTaskFinish += (finish) =>
                {
                    Task.Remove( finish );
                    FinishTask.Add( finish );
                    var start = new DateTime( finish.StartStamp );
                    var last = DateTime.Now;
                    NoticeMessage = $"文件传输完毕,耗时:{( last - start ).TotalMilliseconds}ms";
                };

                try
                {
                    var e = ( from re in Task where re.Hash == task.Hash select re ).Single();
                    e.IPAddress = task.IPAddress;
                    e.Port = task.Port;
                    core.Connect( e );
                    Timer.TimerPeroid += () =>
                    {
                        e.Speed = e.CurrentPosition - e.SpeedTime;
                        e.SpeedTime = e.CurrentPosition;
                    };
                    NoticeIcon = "";
                    NoticeMessage = "用户确认接收文件，传输开始";
                }
                catch
                {

                }
            };
            TransmitService.OnUserRefuse += (task, reason) =>
            {
                var e = ( from re in Task where re.Hash == task.Hash select re ).Single();
                e.IPAddress = task.IPAddress;
                e.Port = task.Port;
                Task.Remove( e );
                NoticeIcon = "";
                NoticeMessage = "用户拒绝了接收文件";
            };

            #endregion


            FileDrop = new Command.FileDrop( Task );
            //第一次发现
            ConnectionService.FindComputer();

            FolderPicker = new Command.FolderPicker( this, Setting );

            
        }

        #region Collection

        public AsyncObservableCollection<Connection> ActiveConnection { get; set; }
            = new AsyncObservableCollection<Connection>();

        public AsyncObservableCollection<Message> MessagePool { get; set; }
            = new AsyncObservableCollection<Message>();

        public AsyncObservableCollection<NetworkTask> Task { get; set; }
            = new AsyncObservableCollection<NetworkTask>();

        public AsyncObservableCollection<NetworkTask> FinishTask { get; set; }
            = new AsyncObservableCollection<NetworkTask>();
        #endregion

        #region StatusBar

        string _noticeMessage;
        public string NoticeMessage {
            get => _noticeMessage;
            set {
                _noticeMessage = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( NoticeMessage ) ) );
            }
        }

        string _noticeIcon;
        public string NoticeIcon {
            get => _noticeIcon;
            set {
                _noticeIcon = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( NoticeIcon ) ) );
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region Message
        string content;
        public string Content {
            get => content;
            set {
                content = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( Content ) ) );
            }
        }

        Connection _Conn;
        public Connection SelectedConnection {
            get => _Conn;
            set {
                _Conn = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( SelectedConnection ) ) );
            }
        }

        NetworkTask _Task;
        public NetworkTask CurrentSelected {
            get => _Task;
            set {
                _Task = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( CurrentSelected ) ) );
            }
        }
        #endregion

        #region Command

        public ICommand FolderPicker { get; set; }
        public ICommand SendMessage { get; set; } = new Command.SendMessage();
        public ICommand SendFile { get; set; } = new Command.SendFile();
        #endregion

        #region Setting
        public string SavePath {
            get => Setting.SavePath;
            set {
                Setting.SavePath = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( SavePath ) ) );
            }
        }

        public string ErrorPath {
            get => Setting.ErrorPath;
            set {
                Setting.ErrorPath = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( ErrorPath ) ) );
            }
        }

        public string MachineName {
            get => Service.ServiceManager.LocalMachineName;
            set {
                Service.ServiceManager.LocalMachineName = value;
                PropertyChanged?.Invoke( this, new PropertyChangedEventArgs( nameof( MachineName ) ) );
            }
        }
        #endregion
    }
}
